package com.weixing.mall.provider.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.google.common.collect.Lists;
import com.weixing.mall.base.constant.DatePattern;
import com.weixing.mall.base.exception.BusinessException;
import com.weixing.mall.base.utils.EnumUtil;
import com.weixing.mall.base.enums.IsEnableEnum;
import com.weixing.mall.provider.api.model.enums.AgentLevelEnum;
import com.weixing.mall.provider.api.model.enums.AgentRebateRuleEnum;
import com.weixing.mall.provider.api.model.enums.AgentTypeEnum;
import com.weixing.mall.provider.api.model.vo.SysUserVo;
import com.weixing.mall.provider.model.domain.Agent;
import com.weixing.mall.provider.model.domain.AgentBonusGroup;
import com.weixing.mall.provider.model.domain.AgentPromote;
import com.weixing.mall.provider.model.domain.AgentRule;
import com.weixing.mall.provider.model.enums.*;
import com.weixing.mall.provider.service.*;
import com.weixing.mall.provider.util.AgentUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 代理商模块-代理商表 服务实现类
 * </p>
 *
 * @author Small
 * @since 2019-11-18
 */
@Service
public class AgentTranlsServiceImpl implements IAgentTranlsService {
    @Autowired
    private IAgentPromoteService agentPromoteService;
    @Autowired
    private IAgentBonusGroupService agentBonusGroupService;
    @Autowired
    private IAgentService agentService;
    @Autowired
    private IAgentRuleService agentRuleService;

    /**
     * 方法描述: 代理商平移
     * @Author Small
     * @param agent
     * @param transScope
     * @param parentAfter
     * @Date 2020/2/21 15:35
     * @return void
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void transl(Agent agent, TransScopeEnum transScope, Agent parentAfter) {
        // 代理商平移前原始父id
        Long originPId = agent.getParentId();
        // 代理商平移前原始父代理
        Agent originParentAgent = (0 == originPId) ? null : agentService.getById(originPId);
        transl(agent, parentAfter);
        String lockDate = DateUtil.format(new Date(), DatePattern.NORM_DATE_PATTERN);
        agent.setLockDate(lockDate);
        agentService.updateById(agent);
        // 记录代理商等级变动记录
        AgentPromote translate = createAgentPromote(agent, PromTypeEnum.TRANSL, transScope, originPId, IsInitiativeEnum.ACTIVE);
        agentPromoteService.save(translate);
        /*
         * 之前的沟通是：如果是业绩团队队长，平移后该业绩团队解散(只有一级代理和经销商才参与分红)
         * 4月17日去深圳沟通的结果是，平移不破坏原来的分红关系
         */
        int agentLevel = agent.getAgentLevel().intValue();
//        if (AgentLevelEnum.DEALER.getValue().intValue() == agentLevel || AgentLevelEnum.LEVEL_1.getValue().intValue() == agentLevel) {
////            AgentBonusGroup agentBonusGroup = agentBonusGroupService.findByAgentId(agent.getId());
////            if (null != agentBonusGroup) {
////                agentBonusGroup.setIsEnable(IsEnableEnum.DISABLE.getValue());
////                agentBonusGroupService.updateById(agentBonusGroup);
////            }
////        }
        // 如果是个人等级变动，那么平移后所有直接下级代理的父级代理为该代理原来的父级代理
        List<Agent> childList = Lists.newArrayList();
        ArrayList<AgentPromote> transList = Lists.newArrayList();
        if (TransScopeEnum.PERSIONAL == transScope) {
            // 查询代理的直接下级代理
            personalTransl(agent, transScope, originParentAgent, childList, transList, lockDate);
        } else if (TransScopeEnum.GROUP == transScope) {
            //团队变动，子代理无需记录变动记录，因为变动后子代理的直接上下级结构没有发生变动
            groupTransl(agent, childList, lockDate);
        }
        // 更新数据库
        if (CollUtil.isNotEmpty(childList)) {
            agentService.updateBatchById(childList, 100);
        }
        agentPromoteService.saveBatch(transList, 100);
    }

    /**
     * 方法描述:代理商等级变动
     * @Author Small
     * @param agent
     * @param promType
     * @param transScope
     * @param uid
     * @Date 2020/3/16 10:40
     * @return void
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void agentPromotion(Agent agent, PromTypeEnum promType, TransScopeEnum transScope, Long uid) {
        if (PromTypeEnum.UP == promType) {
            promUp(agent, promType, transScope, uid);
        } else {
            promDown(agent, promType, transScope);
        }
    }

    /**
     * 方法描述: 平移到客服下面
     * @Author Small
     * @param agent
     * @param transScope
     * @param kefu
     * @Date 2020/4/23 17:17
     * @return void
     */
    @Override
    public void translToKefu(Agent agent, TransScopeEnum transScope, SysUserVo kefu) {
        Date now = new Date();
        // 代理商平移前原始父id
        Long originPId = agent.getParentId();
        // 代理商平移前原始父代理
        Agent originParentAgent = (null == originPId) ? null : agentService.getById(originPId);
        // 平移到客服下面，那么父级代理就没有了
        agent.setParentId(0L);
        agent.setCustomerId(kefu.getId());
        agent.setCustomerName(kefu.getRealName());
        agent.setCustomerBindTime(now);
        AgentRebateRuleEnum agentRebateRuleEnum = EnumUtil.getIEnum(AgentLevelEnum.class, agent.getAgentLevel()).getRebateRule();
        agent.setRebateRule(agentRebateRuleEnum.getValue());
        // 更新代理结构树
        agent.setAgentTreePath(AgentUtil.calcAgentTreePath(agent));
        // 维护结构树
        AgentUtil.updateAgentTree(agent);
        // 更新分红团队
        agent.setBonusGroupId(null);
        String lockDate = DateUtil.format(now, DatePattern.NORM_DATE_PATTERN);
        agent.setLockDate(lockDate);
        agentService.updateById(agent);
        // 记录代理商等级变动记录
        AgentPromote translate = createAgentPromote(agent, PromTypeEnum.TRANSL, transScope, originPId, IsInitiativeEnum.ACTIVE);
        agentPromoteService.save(translate);
        /*
         * 之前的沟通是：如果是业绩团队队长，平移后该业绩团队解散(只有一级代理和经销商才参与分红)
         * 4月17日去深圳沟通的结果是，平移不破坏原来的分红关系
         */
        int agentLevel = agent.getAgentLevel().intValue();
//        if (AgentLevelEnum.DEALER.getValue().intValue() == agentLevel || AgentLevelEnum.LEVEL_1.getValue().intValue() == agentLevel) {
////            AgentBonusGroup agentBonusGroup = agentBonusGroupService.findByAgentId(agent.getId());
////            if (null != agentBonusGroup) {
////                agentBonusGroup.setIsEnable(IsEnableEnum.DISABLE.getValue());
////                agentBonusGroupService.updateById(agentBonusGroup);
////            }
////        }
        // 如果是个人等级变动，那么平移后所有直接下级代理的父级代理为该代理原来的父级代理
        List<Agent> childList = Lists.newArrayList();
        ArrayList<AgentPromote> transList = Lists.newArrayList();
        if (TransScopeEnum.PERSIONAL == transScope) {
            // 查询代理的直接下级代理
            personalTransl(agent, transScope, originParentAgent, childList, transList, lockDate);
        } else if (TransScopeEnum.GROUP == transScope) {
            //团队变动，子代理无需记录变动记录，因为变动后子代理的直接上下级结构没有发生变动
            groupTransl(agent, childList, lockDate);
        }
        // 更新数据库
        if (CollUtil.isNotEmpty(childList)) {
            agentService.updateBatchById(childList, 100);
        }
        agentPromoteService.saveBatch(transList, 100);
    }

    /**
     * 方法描述: 晋级处理流程
     * @Author Small
     * @param agent
     * @param promType
     * @param transScope
     * @param currentUserId
     * @Date 2019/12/19 17:21
     * @return void
     */
    private void promUp(Agent agent, PromTypeEnum promType, TransScopeEnum transScope, long currentUserId) {
        // 晋升前等级
        int orignlevel = agent.getAgentLevel();
        // 晋升前parentID
        long parentBefore = agent.getParentId();
        Agent parent = (0 == parentBefore) ? null : agentService.getById(parentBefore);
        // 晋升后parentID
        long parentAfter = 0;
        // 晋升后等级
        int newLevel = orignlevel - 1;
        agent.setAgentLevel(newLevel);
        // 当前等级对应的返利规则
        int newRebateule = AgentUtil.getRebateRuleByAgentLevel(newLevel).getValue();
        String treePath = null;
        // 是否有父级代理
        Agent pparent = null;
        if (null != parent) {
            agent.setOrgParentId(parent.getId());
            agent.setOrgParentLv(parent.getAgentLevel());
            // 与原上级代理等级存在跨级情况，那么晋升后上级还是原来的上级
            if (orignlevel - parent.getAgentLevel().intValue() > 1) {
                parentAfter = parent.getId();
                newRebateule = AgentUtil.calcAgentRebateRule(parent.getRebateRule(), newLevel).getValue();
                treePath = AgentUtil.calcAgentTreePath(parent.getAgentTreePath(), agent);
            } else {
                // 与上级代理等级不存在跨级情况
                // 原上级还有上级代理，晋升后父级代理为上级的上级
                if (0 != parent.getParentId()) {
                    pparent = agentService.getById(parent.getParentId());
                    newRebateule = AgentUtil.calcAgentRebateRule(pparent.getRebateRule(), newLevel).getValue();
                    parentAfter = pparent.getId();
                    treePath = AgentUtil.calcAgentTreePath(pparent.getAgentTreePath(), agent);
                } else {
                    // 原上级没有上级，晋升后上级代理为0
                    treePath = AgentUtil.calcAgentTreePath(agent);
                }
            }

        } else {
            treePath = AgentUtil.calcAgentTreePath(agent);
        }

        agent.setAgentTreePath(treePath);
        AgentUtil.updateAgentTree(agent);
        agent.setRebateRule(newRebateule);
        agent.setParentId(parentAfter);
        // 晋升上去的代理等级都是银级
        agent.setAgentType(AgentTypeEnum.SILVER.getValue());
        // 对应的等级折扣
        AgentRule agentRule = agentRuleService.selectByLevelAndType(newLevel, AgentTypeEnum.SILVER.getValue());
        agent.setDiscount(agentRule.getDiscount());
        // 设置交易锁定时间（等级变动当天，不允许代理商交易）
        String lockDate = DateUtil.format(new Date(), DatePattern.NORM_DATE_PATTERN);
        agent.setLockDate(lockDate);
        agentService.updateById(agent);
        // 记录等级变更记录
        AgentPromote agentPromote = createAgentPromote(agent, promType, transScope, parentBefore, IsInitiativeEnum.ACTIVE);
        agentPromoteService.save(agentPromote);
        // 处理是否有分红关系产生
        doBonusGroup(agent, orignlevel, parent, newLevel, pparent, PromTypeEnum.UP);
        ArrayList<Agent> childList = Lists.newArrayList();
        ArrayList<AgentPromote> childProList = Lists.newArrayList();
        if (TransScopeEnum.GROUP == transScope) {
            // 如果是团队晋升
            doGroupPromUp(agent, promType, transScope, childList, childProList, lockDate);
        } else {
            doPersionalPromUp(agent, childList, lockDate);
        }
        if (CollUtil.isNotEmpty(childList)) {
            agentService.updateBatchById(childList, 100);
        }
        agentPromoteService.saveBatch(childProList, 100);
    }

    private void transl(Agent agent, Agent parentAfter) {
        // 更新代理的父级id
        agent.setParentId(parentAfter.getId());
        agent.setCustomerId(parentAfter.getCustomerId());
        agent.setCustomerName(parentAfter.getCustomerName());
        agent.setCustomerBindTime(new Date());
        AgentRebateRuleEnum agentRebateRuleEnum = AgentUtil.calcAgentRebateRule(parentAfter.getRebateRule().intValue(), agent.getAgentLevel().intValue());
        agent.setRebateRule(agentRebateRuleEnum.getValue());
        // 更新代理结构树
        agent.setAgentTreePath(AgentUtil.calcAgentTreePath(parentAfter.getAgentTreePath(), agent));
        // 维护结构树
        AgentUtil.updateAgentTree(agent);
        // 更新分红团队
        agent.setBonusGroupId(parentAfter.getBonusGroupId());
    }

    /**
     * 方法描述: 个人平移
     * @Author Small
     * @param agent       代理商
     * @param transScope  变动范围
     * @param originParentAgent 原始父级代理
     * @param childList
     * @param transList
     * @Date 2020/3/13 10:56
     * @return void
     */
    private void personalTransl(Agent agent, TransScopeEnum transScope, Agent originParentAgent, List<Agent> childList, ArrayList<AgentPromote> transList, String lockDate) {
        List<Agent> children = agentService.findByParentId(agent.getId());
        if (CollUtil.isNotEmpty(children)) {
            // 批量更新父级id为原上级代理的直接上级
            int size = children.size();
            AgentPromote childTrans = null;
            for (int i = 0; i < size; i++) {
                Agent child = children.get(i);
                // 计算平移后子代理的返利规则
                if (null == originParentAgent) {
                    child.setRebateRule(AgentUtil.getRebateRuleByAgentLevel(child.getAgentLevel().intValue()).getValue());
                    child.setAgentTreePath(AgentUtil.calcAgentTreePath(child));
                    AgentUtil.updateAgentTree(child);
                    child.setParentId(null);
                    child.setBonusGroupId(null);
                } else {
                    AgentRebateRuleEnum childRebateRuleEnum = AgentUtil.calcAgentRebateRule(originParentAgent.getRebateRule().intValue(), child.getAgentLevel().intValue());
                    child.setRebateRule(childRebateRuleEnum.getValue());
                    child.setAgentTreePath(AgentUtil.calcAgentTreePath(originParentAgent.getAgentTreePath(), child));
                    AgentUtil.updateAgentTree(child);
                    child.setParentId(originParentAgent.getId());
                    child.setBonusGroupId(originParentAgent.getBonusGroupId());
                }
                // 代理商等级变动记录
                childTrans = createAgentPromote(child, PromTypeEnum.TRANSL, transScope, agent.getId(), IsInitiativeEnum.PASSIVE);
                transList.add(childTrans);
                child.setLockDate(lockDate);
                childList.add(child);
                personalTransl(child, transScope, agent, childList, transList, lockDate);
            }
        }
    }


    /**
     * 方法描述: 团队平移
     * @Author Small
     * @param agent
     * @param updateList
     * @Date 2020/3/14 14:15
     * @return void
     */
    private void groupTransl(Agent agent, List<Agent> updateList, String lockDate) {
        int agentRebateRule = agent.getRebateRule().intValue();
        List<Agent> children = agentService.findByParentId(agent.getId());
        if (CollUtil.isNotEmpty(children)) {
            int size = children.size();
            Date date = new Date();
            for (int i = 0; i < size; i++) {
                Agent child = children.get(i);
                child.setCustomerId(agent.getCustomerId());
                child.setCustomerName(agent.getCustomerName());
                child.setCustomerBindTime(date);
                AgentRebateRuleEnum childRebateRuleEnum = AgentUtil.calcAgentRebateRule(agentRebateRule, child.getAgentLevel().intValue());
                child.setRebateRule(childRebateRuleEnum.getValue());
                child.setAgentTreePath(AgentUtil.calcAgentTreePath(agent.getAgentTreePath(), child));
                AgentUtil.updateAgentTree(child);
                child.setBonusGroupId(agent.getBonusGroupId());
                child.setLockDate(lockDate);
                groupTransl(child, updateList, lockDate);
            }
            updateList.addAll(children);
        }
    }


    /**
     * 方法描述: 降级处理流程
     * @Author Small
     * @param agent
     * @param promType
     * @param transScope
     * @Date 2019/12/19 17:21
     * @return void
     */
    private void promDown(Agent agent, PromTypeEnum promType, TransScopeEnum transScope) {

        // 0824 跟客户沟通，存在三角关系禁止降级
        boolean hasGroup = agentBonusGroupService.hasGroup(agent.getId());
        if (hasGroup) {
            throw new BusinessException("该代理存在三角分红关系禁止降级");
        }


        /*
         * 代理商降级
         * 1、降级会涉及到返利规则的变动
         * 2、降级会涉及到代理商结构树的变动
         * 3、降级后原有分红关系自动解除（如需维持，后台客服人员手动维护）
         * 4、降级需要记录等级变动记录
         */
        // 等级变动前的代理等级
        int orignlevel = agent.getAgentLevel();
        // 等级变动后的代理等级
        int newLevel = orignlevel + 1;
        // 代理商原始父级id
        long parentBefore = agent.getParentId();
        Agent parent = (0 == parentBefore) ? null : agentService.getById(parentBefore);
        agent.setAgentLevel(newLevel);
        // 当前等级对应的返利规则
        int newRebateule = (null == parent) ? AgentUtil.getRebateRuleByAgentLevel(newLevel).getValue() : AgentUtil.calcAgentRebateRule(parent.getRebateRule(), newLevel).getValue();
        // 代理结构树变动
        String treePath = (null == parent) ? AgentUtil.calcAgentTreePath(agent) : AgentUtil.calcAgentTreePath(parent.getAgentTreePath(), agent);
        agent.setAgentTreePath(treePath);
        agent.setRebateRule(newRebateule);
        // 降级后的折扣
        AgentRule agentRule = agentRuleService.selectByLevelAndType(newLevel, agent.getAgentType());
        agent.setDiscount(agentRule.getDiscount());
        String lockDate = DateUtil.format(new Date(), DatePattern.NORM_DATE_PATTERN);
        agent.setLockDate(lockDate);
        AgentUtil.updateAgentTree(agent);
        // 代理商等级变动记录
        AgentPromote agentPromote = createAgentPromote(agent, promType, transScope, parentBefore, IsInitiativeEnum.ACTIVE);
        // 降级后下级代理变动关系
        ArrayList<Agent> childList = Lists.newArrayList();
        ArrayList<AgentPromote> childProList = Lists.newArrayList();
        if (TransScopeEnum.GROUP == transScope) {
            // 如果是团队降级
            doGroupPromDown(agent, promType, transScope, childList, childProList, lockDate);
        } else {
            // 个人降级
            doPersionalPromDown(agent);
        }
        // 处理降级后的分红关系
        agentService.updateById(agent);
        agentPromoteService.save(agentPromote);
        if (CollUtil.isNotEmpty(childList)) {
            agentService.updateBatchById(childList, 100);
        }
        agentPromoteService.saveBatch(childProList, 100);
    }

    /**
     * 方法描述: 计算代理商分红关系
     *
     * @param agent    代理商
     * @param orignlevel  原代理等级
     * @param parent    父级代理
     * @param newLevel  现代理等级
     * @param pparent   父类的父类
     * @Date 2020/3/16 9:50
     */
    private void doBonusGroup(Agent agent, int orignlevel, Agent parent, int newLevel, Agent pparent, PromTypeEnum promType) {
        /*
         * 判断是否涉及到分红
         * 1、晋升后等级为一级代理或者经销商时才会涉及到分红
         * 2、只有主动晋升才涉及到分红
         * 3、晋升前存在没有跳级的父级关系，会涉及到直接分红
         * 4、再次晋级会涉及到间接分红关系
         * 5、20200901 客户定的最终分红逻辑，有微信聊天记录为证，再改逻辑客户就是屎
         * 6，20220318 客户改逻辑了，次奥
         * 7，分红发放人全部改为客服（原有逻辑分红发放人可能为经销商）
         */
        AgentBonusGroup agentBonusGroup = null;
        if (PromTypeEnum.UP == promType) {
            if (AgentLevelEnum.DEALER.getValue().intValue() == newLevel || AgentLevelEnum.LEVEL_1.getValue().intValue() == newLevel) {
                if (null != parent && orignlevel - parent.getAgentLevel().intValue() == 1) {
                    // 查看是否已有分红关系，如果没有就是首次晋级
                    agentBonusGroup = agentBonusGroupService.findByAgentId(agent.getId());
                    if (null == agentBonusGroup) {
                        // 如果还没有分红关系，则新建，此时的分红关系一定是直接分红关系
                        agentBonusGroup = new AgentBonusGroup();
                        agentBonusGroup.setAgentId(agent.getId());
                        agentBonusGroup.setAgentName(agent.getAgentName());
                        agentBonusGroup.setAgentLevel(agent.getAgentLevel());
                        agentBonusGroup.setPromoteFirstLevel(agent.getAgentLevel());
                        agentBonusGroup.setIsEnable(IsEnableEnum.ENABLE.getValue());
                        agentBonusGroup.setCreatedTime(new Date());
                        agentBonusGroup.setObligeeId1st(parent.getId());
                        agentBonusGroup.setObligee1st(parent.getAgentName());
                        agentBonusGroup.setObligeeSn1st(parent.getAgentSn());
                        agentBonusGroup.setObligee1stLevel(parent.getAgentLevel());
                        agentBonusGroup.setObligee1stCreateTime(new Date());
                        // 如果晋级后成为一级代理
                        if (AgentLevelEnum.LEVEL_1.getValue().equals(parent.getAgentLevel())) {
                            // 如果上级没有上级，则债务人为客服
                            if (null == pparent) {
                                agentBonusGroup.setObligor1st(parent.getCustomerId());
                                agentBonusGroup.setObligorRole1st(ObligorRoleEnum.COMPANY.getValue());
                                agentBonusGroup.setObligor1stLevel(AgentLevelEnum.KEFU.getValue());
                                agentBonusGroup.setObligor1stName(parent.getCustomerName());
                            } else {
                                agentBonusGroup.setObligor1st(pparent.getId());
                                agentBonusGroup.setObligorRole1st(ObligorRoleEnum.AGENT.getValue());
                                agentBonusGroup.setObligor1stLevel(AgentLevelEnum.DEALER.getValue());
                                agentBonusGroup.setObligor1stName(pparent.getAgentName());
                            }
                            // 处理绑定非正常情况下产生的分红关系（三个平一级的情况）
                            bindUnnormalGroup(agent,parent,agentBonusGroup);
                            // 晋级后成为经销商
                        } else if (AgentLevelEnum.DEALER.getValue().equals(parent.getAgentLevel())) {
                            agentBonusGroup.setObligor1st(parent.getCustomerId());
                            agentBonusGroup.setObligorRole1st(ObligorRoleEnum.COMPANY.getValue());
                            agentBonusGroup.setObligor1stLevel(AgentLevelEnum.KEFU.getValue());
                            agentBonusGroup.setObligor1stName(parent.getCustomerName());
                            // 判断是否是一级分红团队，如果是则将他所属的分红团队的发放人置为客服
                            // 代理为一级分红团队
                            doUpdateObligorLv1(agent);
                            // 20200901 判断原上级是否存在分红关系，如果存在则将原上级的一级分红关系，设置为该代理的二级分红关系
                            handleUpToDe(parent, agentBonusGroup);
                            // 处理解绑非正常情况下产生的分红关系（三个平一级的情况）
                            unbindUnnormalGroup(agent);
                        }
                        agentBonusGroup.setIsLv1enable(IsEnableEnum.ENABLE.getValue());
//                        agentBonusGroup.setKefuId(agent.getCustomerId());
//                        agentBonusGroup.setKefuName(agent.getCustomerName());
                        agentBonusGroup.setIsNormal(IsEnableEnum.ENABLE.getValue());
                    } else {
                        /*
                         * 如果存在分红关系记录
                         * 1、代理之间的分红关系有可能随着代理的平移操作，原有的分红关系被破坏，所以必须判断分红关系是否可用
                         * 2、如果不可用，说明原有分红关系已被破坏，此时应该是重新计算直接分红关系
                         * 3、如果可用，此时应该是计算间接分红关系
                         */
                        agentBonusGroup.setAgentLevel(agent.getAgentLevel());
                        if (IsEnableEnum.DISABLE.getValue().equals(agentBonusGroup.getIsLv1enable())) {
                            agentBonusGroup.setIsEnable(IsEnableEnum.ENABLE.getValue());
                            agentBonusGroup.setPromoteFirstLevel(agent.getAgentLevel());

                            agentBonusGroup.setObligeeId1st(parent.getId());
                            agentBonusGroup.setObligee1st(parent.getAgentName());
                            agentBonusGroup.setObligee1stLevel(parent.getAgentLevel());
                            agentBonusGroup.setObligee1stCreateTime(new Date());
                            // 如果晋级后成为一级代理
                            if (AgentLevelEnum.LEVEL_1.getValue().equals(parent.getAgentLevel())) {
                                // 如果上级没有上级，则债务人为客服
                                if (null == pparent) {
                                    agentBonusGroup.setObligor1st(parent.getCustomerId());
                                    agentBonusGroup.setObligorRole1st(ObligorRoleEnum.COMPANY.getValue());
                                    agentBonusGroup.setObligor1stLevel(AgentLevelEnum.KEFU.getValue());
                                    agentBonusGroup.setObligor1stName(parent.getCustomerName());
                                } else {
                                    agentBonusGroup.setObligor1st(pparent.getId());
                                    agentBonusGroup.setObligorRole1st(ObligorRoleEnum.AGENT.getValue());
                                    agentBonusGroup.setObligor1stLevel(AgentLevelEnum.DEALER.getValue());
                                    agentBonusGroup.setObligor1stName(pparent.getAgentName());
                                }
                                // 处理绑定非正常情况下产生的分红关系（三个平一级的情况）
                                bindUnnormalGroup(agent,parent,agentBonusGroup);
                                // 晋级后成为经销商
                            } else if (AgentLevelEnum.DEALER.getValue().equals(parent.getAgentLevel())) {
                                agentBonusGroup.setObligor1st(parent.getCustomerId());
                                agentBonusGroup.setObligorRole1st(ObligorRoleEnum.COMPANY.getValue());
                                agentBonusGroup.setObligor1stLevel(AgentLevelEnum.KEFU.getValue());
                                agentBonusGroup.setObligor1stName(parent.getCustomerName());
                                // 判断是否是一级分红团队，如果是则将他所属的分红团队的发放人置为客服
                                // 代理为一级分红团队
                                doUpdateObligorLv1(agent);
                                handleUpToDe(parent, agentBonusGroup);
                                // 处理解绑非正常情况下产生的分红关系（三个平一级的情况）
                                unbindUnnormalGroup(agent);
                            }
                            agentBonusGroup.setIsLv1enable(IsEnableEnum.ENABLE.getValue());
//                            agentBonusGroup.setKefuId(agent.getCustomerId());
//                            agentBonusGroup.setKefuName(agent.getCustomerName());
                            agentBonusGroup.setIsNormal(IsEnableEnum.ENABLE.getValue());
                        } else {
                            if (0 == agentBonusGroup.getObligeeId1st() && 0 != agentBonusGroup.getObligeeId2nd()) {
                                throw new BusinessException("业务数据异常，请联系系统管理员解决");
                            } else {
                                agentBonusGroup.setObligeeId2nd(parent.getId());
                                agentBonusGroup.setObligee2nd(parent.getAgentName());
                                agentBonusGroup.setObligee2ndLevel(parent.getAgentLevel());
                                agentBonusGroup.setObligee2ndCreateTime(new Date());
                                // 二次晋升后的等级一定是经销商，债务人一定是公司
                                agentBonusGroup.setObligor2nd(parent.getCustomerId());
                                agentBonusGroup.setObligorRole2nd(ObligorRoleEnum.COMPANY.getValue());
                                agentBonusGroup.setObligor2ndLevel(AgentLevelEnum.KEFU.getValue());
                                agentBonusGroup.setObligor2ndName(parent.getCustomerName());
                                agentBonusGroup.setObligeeSn2nd(parent.getAgentSn());
                                agentBonusGroup.setIsLv2enable(IsEnableEnum.ENABLE.getValue());
                                // 处理解绑非正常情况下产生的分红关系（三个平一级的情况）
                                unbindUnnormalGroup(agent);
                            }
                        }
                    }
                }
            }
        }
        // 0824 日确定 有三角关系不让降级
        // 新增或者更新代理商分红关系记录表
        if (null != agentBonusGroup) {
            agentBonusGroupService.saveOrUpdate(agentBonusGroup);
        }
    }


    /**
     * 解除3个平一级分红关系
     * @apiNote 如果代理再次晋升成为经销商后，3个平一级分红关系自定解除
     * @param agent  代理商
     */
    private void unbindUnnormalGroup(Agent agent){
        AgentBonusGroup group = agentBonusGroupService.findByAgentIdAndNormalState(agent.getId(),IsEnableEnum.DISABLE.getValue());
        if (null != group && IsEnableEnum.ENABLE.getValue().equals(group.getIsEnable())){
            group.setIsEnable(IsEnableEnum.DISABLE.getValue());
            group.setIsLv1enable(IsEnableEnum.DISABLE.getValue());
            group.setLv1remark("晋升成为经销商后，3个平一级分红关系自动解除");
            agentBonusGroupService.updateById(group);
        }
    }

    /**
     * 绑定3个平一级的分红关系
     *
     * @param agent     代理
     * @param parent    原上级
     * @param agentBonusGroup  当前的分红关系
     */
    private void bindUnnormalGroup(Agent agent,Agent parent,AgentBonusGroup agentBonusGroup){
         /*
          * 产生三个平一级B,D分红的必要条件
          * 原关系：经销商（A），一级代理B，二级代理C，三级代理D
          * 1、代理本身晋升成为一级代理
          * 2、代理存在原上级，并且原上级也是一级代理
          * 3、代理原上级的原上级存在，并且也是一级代理
         */
         // 1、判断代理是否为一级代理(D)
        if (AgentLevelEnum.LEVEL_1.getValue().equals(agent.getAgentLevel())){
            // 2、判断代理的原上级是否为一级代理(C)
            if (AgentLevelEnum.LEVEL_1.getValue().equals(parent.getAgentLevel())){
                // 3.1、判断代理的原上级的原上级是否存在
                if (null != parent.getOrgParentId()){
                    // 3.2、判断原上级的原上级是否为一级代理(B)
                    Agent orgPParent = agentService.getById(parent.getOrgParentId());
                    if (AgentLevelEnum.LEVEL_1.getValue().equals(orgPParent.getAgentLevel())){
                        // 3.3、判断原上级和原上级的原上级之间是否存在分红关系
                        AgentBonusGroup groupAbc = agentBonusGroupService.findByAgentIdAndNormalState(parent.getId(), IsEnableEnum.ENABLE.getValue());
                        if (null != groupAbc && IsEnableEnum.ENABLE.getValue().equals(groupAbc.getIsEnable())){
                            if (groupAbc.getObligeeId1st().longValue() == orgPParent.getId().longValue()
                               && groupAbc.getObligor1st().longValue() == agentBonusGroup.getObligor1st().longValue()){
                                // 3.4、B和D产生分红关系
                                AgentBonusGroup groupAbd = new AgentBonusGroup();
                                groupAbd.setAgentId(agent.getId());
                                groupAbd.setAgentName(agent.getAgentName());
                                groupAbd.setAgentLevel(agent.getAgentLevel());
                                groupAbd.setPromoteFirstLevel(agent.getAgentLevel());
                                groupAbd.setIsEnable(IsEnableEnum.ENABLE.getValue());
                                groupAbd.setCreatedTime(new Date());
                                groupAbd.setObligeeId1st(orgPParent.getId());
                                groupAbd.setObligee1st(orgPParent.getAgentName());
                                groupAbd.setObligeeSn1st(orgPParent.getAgentSn());
                                groupAbd.setObligee1stLevel(orgPParent.getAgentLevel());
                                groupAbd.setObligee1stCreateTime(new Date());
                                groupAbd.setObligor1st(agentBonusGroup.getObligor1st());
                                groupAbd.setObligorRole1st(agentBonusGroup.getObligorRole1st());
                                groupAbd.setObligor1stLevel(agentBonusGroup.getObligor1stLevel());
                                groupAbd.setObligor1stName(agentBonusGroup.getObligor1stName());
                                groupAbd.setIsLv1enable(IsEnableEnum.ENABLE.getValue());
                                groupAbd.setIsNormal(IsEnableEnum.DISABLE.getValue());
//                                groupAbd.setKefuId(agent.getCustomerId());
//                                groupAbd.setKefuName(agent.getCustomerName());
                                groupAbd.setLv1remark(agent.getAgentName() + "晋升为一级代理后和" + parent.getAgentName()+" 与 "
                                        + orgPParent.getAgentName() + "形成3个平一级关系，与" + orgPParent.getAgentName() + "产生分红关系");
                                agentBonusGroupService.save(groupAbd);
                            }
                        }
                    }
                }
            }
        }

    }

    private void handleUpToDe(Agent parent, AgentBonusGroup agentBonusGroup) {
        // 20200901 判断原上级是否存在分红关系，如果存在则将原上级的一级分红关系，设置为该代理的二级分红关系
        AgentBonusGroup agentBonusGroupP = agentBonusGroupService.findByAgentId(parent.getId());
        if (null != agentBonusGroupP) {
            if (WhetherEnum.YES.getValue().equals(agentBonusGroupP.getIsLv1enable())) {
                agentBonusGroup.setObligee2nd(agentBonusGroupP.getObligee1st());
                agentBonusGroup.setObligeeId2nd(agentBonusGroupP.getObligeeId1st());
                agentBonusGroup.setObligee2ndLevel(agentBonusGroupP.getObligee1stLevel());
                agentBonusGroup.setObligee2ndCreateTime(new Date());
                agentBonusGroup.setObligeeSn2nd(agentBonusGroupP.getObligeeSn1st());
                agentBonusGroup.setIsLv2enable(com.weixing.mall.base.enums.WhetherEnum.YES.getValue());
                // 分红人
                agentBonusGroup.setObligor2nd(parent.getCustomerId());
                agentBonusGroup.setObligorRole2nd(ObligorRoleEnum.COMPANY.getValue());
                agentBonusGroup.setObligor2ndLevel(AgentLevelEnum.KEFU.getValue());
                agentBonusGroup.setObligor2ndName(parent.getCustomerName());
            }
        }
    }

    private void doUpdateObligorLv1(Agent agent) {
        QueryWrapper<AgentBonusGroup> wrapper1 = new QueryWrapper<>();
        wrapper1.eq("obligee_id1st", agent.getId()).eq("is_lv1enable", IsEnableEnum.ENABLE.getValue());
        List<AgentBonusGroup> list1 = agentBonusGroupService.list(wrapper1);
        if (CollUtil.isNotEmpty(list1)) {
            for (AgentBonusGroup group : list1) {
                group.setObligor1st(agent.getCustomerId());
                group.setObligor1stName(agent.getCustomerName());
                group.setObligorRole1st(ObligorRoleEnum.COMPANY.getValue());
                group.setLv1remark("代理id" + agent.getId() + "晋升成为经销商，变更分红发放人为客服");
                agentBonusGroupService.updateById(group);
            }
        }
    }

    /**
     * 方法描述: 团队晋级
     * @Author Small
     * @param agent
     * @param promType
     * @param transScope
     * @param childList
     * @param childProList
     * @Date 2019/12/19 17:06
     * @return void
     */
    private void doGroupPromUp(Agent agent, PromTypeEnum promType, TransScopeEnum transScope, ArrayList<Agent> childList, ArrayList<AgentPromote> childProList, String lockDate) {
        List<Agent> children = agentService.findByParentId(agent.getId());
        if (CollUtil.isNotEmpty(children)) {
            int size = children.size();
            for (int i = 0; i < size; i++) {
                Agent child = children.get(i);
                int childOrignLevel = child.getAgentLevel();
                int childNewLevel = childOrignLevel - 1;
                long childParentBefore = agent.getId();
                // 更新
                child.setAgentLevel(childNewLevel);
                int childNewRebateRule = AgentUtil.calcAgentRebateRule(agent.getRebateRule(), childNewLevel).getValue();
                String treePath = AgentUtil.calcAgentTreePath(agent.getAgentTreePath(), child);
                child.setRebateRule(childNewRebateRule);
                child.setAgentTreePath(treePath);
                AgentUtil.updateAgentTree(child);
                child.setBonusGroupId(agent.getBonusGroupId());
                // 更新折扣信息
                AgentRule agentRule = agentRuleService.selectByLevelAndType(childNewLevel, AgentTypeEnum.SILVER.getValue());
                child.setDiscount(agentRule.getDiscount());
                child.setAgentType(AgentTypeEnum.SILVER.getValue());
                child.setLockDate(lockDate);
                childList.add(child);
                // 等级变更记录
                AgentPromote childPromote = createAgentPromote(child, promType, transScope, childParentBefore, IsInitiativeEnum.PASSIVE);
                childProList.add(childPromote);
                doGroupPromUp(child, promType, transScope, childList, childProList, lockDate);
            }
        }
    }

    /**
     * 方法描述: 团队降级
     * @Author Small
     * @param agent
     * @param promType
     * @param transScope
     * @param childList
     * @param childProList
     * @Date 2019/12/19 17:06
     * @return void
     */
    private void doGroupPromDown(Agent agent, PromTypeEnum promType, TransScopeEnum transScope, ArrayList<Agent> childList, ArrayList<AgentPromote> childProList, String lockDate) {
        /*
         * 团队降级
         * 1、如果团队内部包含最低级等级，比如最低等级为三级代理，如果团队内包含三级代理，那么提示客服将三级平移后在进行团队降级
         * 2、降级后所有子代理的返利规则变化
         * 3、降级后所有子代理的代理商结构树变化
         * 4、降级后所有子代理的所属分红团队变化
         *
         */
        Integer oldLevel = agent.getAgentLevel().intValue() - 1;
        List<Agent> lastLevelNodes = agentService.selectLastLevelListByAgentTreeNode(agent, oldLevel);
        if (CollUtil.isNotEmpty(lastLevelNodes)) {
            throw new BusinessException("该代理下面有三级子代理，您不能直接选择团队降级，请先将子代理平移后再降级");
        }
        List<Agent> children = agentService.findByParentId(agent.getId());
        if (CollUtil.isNotEmpty(children)) {
            int size = children.size();
            for (int i = 0; i < size; i++) {
                Agent child = children.get(i);
                int childOrignLevel = child.getAgentLevel();
                int childNewLevel = childOrignLevel + 1;
                long childParentBefore = agent.getId();
                child.setAgentLevel(childNewLevel);
                int childNewRebateRule = AgentUtil.calcAgentRebateRule(agent.getRebateRule(), childNewLevel).getValue();
                String treePath = AgentUtil.calcAgentTreePath(agent.getAgentTreePath(), child);
                child.setRebateRule(childNewRebateRule);
                child.setAgentTreePath(treePath);
                AgentUtil.updateAgentTree(child);
                child.setLockDate(lockDate);
                AgentRule agentRule = agentRuleService.selectByLevelAndType(childNewLevel, child.getAgentType());
                if (null == agentRule) {
                    throw new BusinessException("系统未配置对应代理等级的折扣信息，等级：" + childNewLevel);
                }
                child.setDiscount(agentRule.getDiscount());
                child.setBonusGroupId(agent.getBonusGroupId());
                childList.add(child);
                // 等级变更记录
                AgentPromote childPromote = createAgentPromote(child, promType, transScope, childParentBefore, IsInitiativeEnum.PASSIVE);
                childProList.add(childPromote);
                doGroupPromDown(child, promType, transScope, childList, childProList, lockDate);
            }
        }
    }

    /**
     * 方法描述: 个人降级
     * @Author Small
     * @param agent
     * @Date 2019/12/19 17:06
     * @return void
     */
    private void doPersionalPromDown(Agent agent) {
        /*
         * 个人降级
         * 个人降级时客服会先把代理下面的子代理平移走，然后再降级，
         * 程序处理只用判断代理下面是否有子代理，如果有就直接提示不让降级
         */
        List<Agent> children = agentService.findByParentId(agent.getId());
        if (CollUtil.isNotEmpty(children)) {
            throw new BusinessException("该代理下面有子代理，您不能直接对其降级，请先将子代理平移后再降级");
        }
    }

    /**
     * 方法描述: 个人晋级
     *
     * @param agent
     * @param childList
     * @Date 2019/12/19 17:06
     * @return void
     */
    private void doPersionalPromUp(Agent agent, ArrayList<Agent> childList, String lockDate) {
        List<Agent> children = agentService.findByParentId(agent.getId());
        if (CollUtil.isNotEmpty(children)) {
            int size = children.size();
            for (int i = 0; i < size; i++) {
                Agent child = children.get(i);
                // 更新
                int childNewRebateRule = AgentUtil.calcAgentRebateRule(agent.getRebateRule(), child.getAgentLevel()).getValue();
                String treePath = AgentUtil.calcAgentTreePath(agent.getAgentTreePath(), child);
                child.setRebateRule(childNewRebateRule);
                child.setAgentTreePath(treePath);
                AgentUtil.updateAgentTree(child);
                child.setBonusGroupId(agent.getBonusGroupId());
                child.setLockDate(lockDate);
                childList.add(child);
                // 递归
                doPersionalPromUp(child, childList, lockDate);
            }
        }
    }


    /**
     * 方法描述: 生成等级变更记录
     * @Author Small
     * @param agent     代理商
     * @param promType  变动类型
     * @param transScope 变动范围
     * @param parentIdBefore 变动前父级代理
     * @Date 2019/12/19 15:49
     * @return com.weixing.mall.provider.model.domain.AgentPromote
     */
    private AgentPromote createAgentPromote(Agent agent, PromTypeEnum promType, TransScopeEnum transScope, Long parentIdBefore, IsInitiativeEnum isInitiative) {
        AgentPromote agentPromote = new AgentPromote();
        agentPromote.setAgentId(agent.getId());
        agentPromote.setChgScope(transScope.getValue());
        // 计算原始等级
        int levelBefore = agent.getAgentLevel();
        int levelAfter = agent.getAgentLevel();
        switch (promType) {
            case UP:
                levelBefore = levelAfter + 1;
                break;
            case DOWN:
                levelBefore = levelAfter - 1;
                break;
            case TRANSL:
                levelBefore = levelAfter;
                break;
            default:
                levelBefore = levelAfter;
                break;
        }
        agentPromote.setLevelBefore(levelBefore);
        agentPromote.setLevelAfter(agent.getAgentLevel());
        agentPromote.setParentBefore(parentIdBefore);
        agentPromote.setParentAfter(agent.getParentId());
        agentPromote.setPromoteType(promType.getValue());
        agentPromote.setIsInitiative(isInitiative.getValue());
        return agentPromote;
    }
}
